package com.cjm.one.security.config;

import com.cjm.one.custom.client.CustomerInfoClient;

import com.cjm.one.custom.client.CustomerLoginLogClient;
import com.cjm.one.security.custom.CustomPasswordEncoder;
import com.cjm.one.security.fillter.AppLoginFilter;
import com.cjm.one.security.fillter.AppTokenAuthenticationFilter;
import com.cjm.one.security.service.AppUserDetailsService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import java.util.List;

@Configuration
@EnableWebSecurity
@Order(2)
@Slf4j
@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
public class AppSecurityConfig {

    @Resource
    private PermissionPathPropertis permissionPathPropertis;
    private final PathMatcher pathMatcher = new AntPathMatcher();
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private CustomerInfoClient customerInfoClient;

    @Resource
    private CustomerLoginLogClient customerLoginLogClient;
    @Resource
    private AuthenticationConfiguration authenticationConfiguration;
    @Bean("appPasswordEncoder")
    public CustomPasswordEncoder appPasswordEncoder() {
        return new CustomPasswordEncoder(); // 确保返回自定义的 PasswordEncoder
    }

    @Bean("appUserDetailsService")
    public UserDetailsService appUserDetailsService() {
        return new AppUserDetailsService();
    }

        @Bean
        public AuthenticationProvider appAuthenticationProvider() {
            DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
            provider.setUserDetailsService(appUserDetailsService());
            provider.setPasswordEncoder(appPasswordEncoder());
            return provider;
        }

    @Bean
    public SecurityFilterChain appFilterChain(HttpSecurity http,
                                              @Qualifier("emailCodeAuthenticationProvider") AuthenticationProvider emailCodeProvider,
                                              @Qualifier("emailPasswordAuthenticationProvider") AuthenticationProvider emailPasswordProvider,
                                              @Qualifier("mobileCodeAuthenticationProvider") AuthenticationProvider mobileCodeProvider) throws Exception {
        http
                .securityMatcher("/app/**")
                .authorizeHttpRequests((authorize)->
                        //放行
                        authorize.requestMatchers(new RequestMatcher() {
                                                      @Override
                                                      public boolean matches(HttpServletRequest request) {
                                                          String requestURI = request.getRequestURI();
                                                          List<String> ignoreUrlList = permissionPathPropertis.getIgnoreUrlList();
                                                          log.info("忽略的url列表permissionPathPropertis:{}",ignoreUrlList);
                                                          log.info("HttpSecurity请求路径: {}", request.getRequestURI());
                                                          for (String url : ignoreUrlList) {
                                                              boolean match = pathMatcher.match(url, requestURI);
                                                              if (match){
                                                                  log.info("匹配到忽略的url: {}", url);
                                                                  return true;
                                                              }
                                                          }
                                                          return false;
                                                      }
                                                  }
                                ).permitAll()
                                .anyRequest().authenticated())
                // 禁用缓存
                .sessionManagement(AbstractHttpConfigurer::disable)
                // 使用无状态session，即不使用session缓存数据
                .formLogin(AbstractHttpConfigurer::disable)
                //HTTP 基本认证
                .httpBasic(AbstractHttpConfigurer::disable)
                .logout(AbstractHttpConfigurer::disable)
                //禁用csrf(防止跨站请求伪造攻击)
                .csrf(AbstractHttpConfigurer::disable)
                // 添加身份验证

                .authenticationProvider(appAuthenticationProvider())
                .authenticationProvider(emailCodeProvider)
                .authenticationProvider(emailPasswordProvider)
                .authenticationProvider(mobileCodeProvider)
                // 添加token过滤器
                .addFilterBefore(new AppTokenAuthenticationFilter(redisTemplate,permissionPathPropertis), UsernamePasswordAuthenticationFilter.class)
                .addFilter(new AppLoginFilter(emailCodeProvider,mobileCodeProvider,emailPasswordProvider, redisTemplate, customerInfoClient,customerLoginLogClient));


        return http.build();
    }
}